package org.example.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Slf4j
//@Aspect
@Order(1)
//order里面的数值越大，先进行执行
//就像一个圆圈，数值大的在外面进行包裹
/**
 * 五种通知方式，其中around通知需要一个返回值
 */
public class AspectDemo1 {
    /**
     * 这个注解里面执行的是第二个星号是指这个controller包下面的所有的controller
     * 然后接着下一个星号是指这个controller类中所有的方法
     * 后面跟上 的是方法的参数
     * <p>
     * 也就是说光around有参数传递，其他通知类型没有参数
     *
     * @param pj
     * @return
     */
//    @Around("@annotation(org.example.aspect.TimeRecord)")
//    public  Object around(ProceedingJoinPoint pj)  {
//        long startTime = System.currentTimeMillis();
//        Object result = null;
//        try{
//           result=pj.proceed();
//        } catch (Throwable e) {
//            throw new RuntimeException(e);
//        }
//        long endTime = System.currentTimeMillis();
//        log.info(pj.toString()+"执行时间:"+(endTime-startTime)+"ms");
//        return result;
//    }
    //切点表达式
//    @Around("execution( * org.example.controller.*.*(..))")
//    public Object around1(ProceedingJoinPoint pj)  {
//        log.info("start around");
//        Object result = null;
//        try{
//            result=pj.proceed();
//        } catch (Throwable e) {
//            throw new RuntimeException(e);
//        }
//        log.info("end around");
//        return result;
//    }
//
//    /**
//     * 在方法执行前都会进行执行
//     * @throws Throwable
//     */
//    @Before("execution(* org.example.controller.*.*(..))")
//    public void before() throws Throwable {
//        log.info("start before");
//        log.info("end before");
//    }
    @After("execution(* org.example.controller.*.*(..))")
    public void after() throws Throwable {
        log.info("after 的方法");
    }

    @Before("execution(* org.example.controller.*.*(..))")
    public void before() throws Throwable {
        log.info("AspectDemo1 的方法");
    }

    //实践出真知
    //当不知道可以试一试代码的方法进行解决
    @AfterReturning("execution(* org.example.controller.*.*(..))")
    public void afterReturning() throws Throwable {
        log.info("after return  的方法");
    }

    @AfterThrowing("execution(* org.example.controller.*.*(..))")
    public void afterThrowing() throws Throwable {
        log.info("AspectDemo1 的方法");
    }

    @Around("execution( * org.example.controller.*.*(..))")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        log.info("around AspectDemo1 ");
        Object result =null;
        try{
            result=pjp.proceed();
        } catch (Throwable e) {
            log.info("捕获异常");
        }
        log.info("around AspectDemo1 ");
        return result;
    }
}
